package com.xiaolin.structure.linked.bothway.loop;

/**
 * @ClassName BothWayLoopLinkedList
 * @Description 双向循环链表
 * @Detail detail
 * @Author MyPC
 * @Date 2020/12/12
 * @Version 1.0
 */
public class BothWayLoopLinkedList<E> {
    private int size;
    Node<E> first;
    Node<E> last;

    /**
     * 链接节点
     * @param e
     */
    private void linkElement(E e){
        if(size==0){
            // 添加第一个元素
            first=new Node<>(null,e,null);
            // 第一个节点的后继节点即是自己
            first.next=first;
            // 最后一个节点即第一个节点
            this.last=first;
            // 第一个元素前驱节点即是末尾节点
            first.pre=last;
        }else {
            // 添加新元素，最后一个元素的后继节点是第一个元素
            last.next=new Node<>(last,e,first);
            // 重新指定新的末尾节点
            last=last.next;
            // 重新指定第一个元素前驱节点
            first.pre=last;
        }
        size++;
    }

    /**
     * 索引校验异常
     * @param index
     */
    private void checkout(int index){
        if(index<0 || index >=size){
            throw new IndexOutOfBoundsException("索引越界");
        }
    }

    /**
     * 添加节点
     * @param e
     * @return
     */
    public boolean add(E e){
        linkElement(e);
        return true;
    }

    /**
     * 索引节点
     * @param index
     * @return
     */
    public E getElement(int index){
        checkout(index);
        Node<E> temp=first;
        for (int i=0;i<index;i++){
            temp=temp.next;
        }
        return temp.item;
    }

    /**
     * 索引节点
     * @param index
     * @return
     */
    public Node<E> getNode(int index){
        checkout(index);
        Node<E> temp=first;
        for (int i=0;i<index;i++){
            temp=temp.next;
        }
        return temp;
    }

    /**
     * 移除元素
     * @param index
     * @return
     */
    public boolean remove(int index){
        checkout(index);
        if(index==0){
            // 移除第一个元素
            first=first.next;
            first.pre=last;
            last.next=first;
        }else if(index == size-1){
            // 移除最后一个元素
            last=last.pre;
            first.pre=last;
            last.next=first;
        }else {
            // 移除中间元素
            Node<E> remove = getNode(index);
            // 要移除的元素的前驱节点
            Node<E> pre = remove.pre;
            // 要移除元素的后继节点
            Node<E> next = remove.next;
            pre.next=next;
            next.pre=pre;
        }
        size--;
        return true;
    }

    public int size(){
        return size;
    }

}
